package com.dragee.modules.sys.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dragee.common.R;
import com.dragee.common.core.domain.AjaxResult;
import com.dragee.config.exception.AuthErrorType;
import com.dragee.config.exception.AuthException;
import com.dragee.config.exception.BusinessErrorType;
import com.dragee.config.exception.BusinessException;
import com.dragee.config.shiro.AuthToken;
import com.dragee.constants.AuthConstants;
import com.dragee.modules.sys.dto.TokenDTO;
import com.dragee.modules.sys.entity.LoginUser;
import com.dragee.modules.sys.entity.SysMenu;
import com.dragee.modules.sys.entity.UserEntity;
import com.dragee.modules.sys.service.ISysMenuService;
import com.dragee.modules.sys.service.ISysRoleService;
import com.dragee.modules.sys.service.UserService;
import com.dragee.modules.sys.service.impl.PermissionService;
import com.dragee.modules.sys.vo.LoginVo;
import com.dragee.modules.sys.vo.UpdatePasswordVo;
import com.dragee.utils.LoginUserUtil;
import com.dragee.utils.TokenUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;
import java.util.Set;

/**
 * @author tys on 11/10/20
 */
@RestController
@Api(tags = "sys - 登陆")
public class LoginController {
    @Autowired
    private UserService userService;
    @Autowired
    private PermissionService permissionService;
    @Autowired
    private ISysMenuService menuService;
    @Autowired
    private ISysRoleService sysRoleService;

    @ApiOperation("登陆")
    @PostMapping("/login")
    public R login (@RequestBody LoginVo loginVo) {
        String tokenStr;
        AuthenticationToken token;
        Subject subject = SecurityUtils.getSubject();

        // 参数校验
        if (StrUtil.isBlank(loginVo.getUsername()) || StrUtil.isBlank(loginVo.getPassword()) || StrUtil.isBlank(loginVo.getClientId()))
        {
            throw new BusinessException(BusinessErrorType.INVALID_PARAMS);
        }
        // 校验clientId
        if (!Arrays.asList(AuthConstants.CLIENTS).contains(loginVo.getClientId())) {
            throw new AuthException(AuthErrorType.NO_SUPPORT_CLIENT);
        }
        // 传入的密码加密
        String password = new Sha256Hash(loginVo.getPassword(), AuthConstants.SLAT_PWD).toHex();
        // String password = loginVo.getPassword();
        // 根据用户名密码去数据库比对用户 获取LoginUser
        UserEntity user = userService.getOne(new QueryWrapper<UserEntity>().eq("username", loginVo.getUsername()), false);
        if (user == null) {
            throw new AuthException(AuthErrorType.USERNAME_NO_EXIST_ERROR);
        }
        if (user.getStatus().equals("0")) {
            throw new AuthException(AuthErrorType.USERNAME_LOCK_ERROR);
        }
        LoginUser loginUser = userService.getLoginUser(loginVo.getUsername(), password);
        if (loginUser == null) {
            throw new AuthException(AuthErrorType.USERNAME_OR_PASSWORD_ERROR);
        }
        loginUser.setClientId(loginVo.getClientId());
        /* loginUser 插入权限 permisstion */
        loginUser.setPermissions(permissionService.getMenuPermissions(user.getUserId()));
        /*增加角色信息*/
        // loginUser.setRoles(userService.getRolePoByUserId(loginUser.getUserId().toString()));
//        List<RolePo> roles = userService.getRolePoByUserId(loginUser.getUserId().toString());
//        RolePo rolePoUp = roles.stream().filter(r -> r.getLevel() >= 0)
//                .min((Comparator.comparingInt(RolePo::getLevel))).orElse(null);
//        RolePo rolePoDown = roles.stream().filter(r -> r.getLevel() < 0)
//                .max((Comparator.comparingInt(RolePo::getLevel))).orElse(null);
//        loginUser.setHighRoleUp(rolePoUp);
//        loginUser.setHighRoleDown(rolePoDown);
        // 将loginUser对象放到token中
        tokenStr = TokenUtil.createToken(loginUser, AuthConstants.TOKEN_EXPIRE);
        // 用户登陆 返回token
        token = new AuthToken(tokenStr);
        /*核心 调用认证方法*/
        try  {
            subject.login(token);
            TokenDTO dto = new TokenDTO(AuthConstants.JWT_TOKEN_HEADER,
                    AuthConstants.JWT_TOKEN_PREFIX + tokenStr,
                    loginUser.getUserId(),
                    loginUser.getUsername(),
                    loginUser.getRoleName(),
                    loginUser.getName());

            return R.ok().put("data", dto);
        } catch (BusinessException e) {
            return R.error(e.getCode(), e.getMessage());
        } catch (Exception e) {
            return R.error();
        }
    }




    @ApiOperation("修改密码")
    @PostMapping("/update-password")
    public R updatePassword (@RequestBody UpdatePasswordVo vo) {

        // 传入的密码加密
        String password = new Sha256Hash(vo.getOldPassword(), AuthConstants.SLAT_PWD).toHex();
        // 根据用户名密码去数据库比对用户 获取LoginUser
        LoginUser loginUser = userService.getLoginUser(vo.getUsername(), password);
        if (loginUser == null) {
            //比对失败
            throw new AuthException(AuthErrorType.USERNAME_PASSWORD_ERROR);
        }
        userService.updatePassword(vo);
        return R.ok();
    }

    @GetMapping("getInfo")
    @ApiOperation("获取当前登陆人权限和菜单")
    public AjaxResult userInfo () {
        LoginUser loginUser = LoginUserUtil.getLoginUser();
        UserEntity user = userService.getById(loginUser.getUserId());
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(loginUser.getUserId());
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermissions(loginUser.getUserId());
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", loginUser);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        ajax.put("avatar",user.getAvatar());
        return ajax;
    }

    @GetMapping("getRouters")
    @ApiOperation("获取Router")
    public AjaxResult getRouters()
    {
//        String s = "{\"data\":[{\"name\":\"System\",\"path\":\"/system\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"Layout\",\"alwaysShow\":true,\"meta\":{\"title\":\"系统管理\",\"icon\":\"system\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"User\",\"path\":\"user\",\"hidden\":false,\"component\":\"system/user/index\",\"meta\":{\"title\":\"用户管理\",\"icon\":\"user\",\"noCache\":false,\"link\":null}},{\"name\":\"Role\",\"path\":\"role\",\"hidden\":false,\"component\":\"system/role/index\",\"meta\":{\"title\":\"角色管理\",\"icon\":\"peoples\",\"noCache\":false,\"link\":null}},{\"name\":\"Menu\",\"path\":\"menu\",\"hidden\":false,\"component\":\"system/menu/index\",\"meta\":{\"title\":\"菜单管理\",\"icon\":\"tree-table\",\"noCache\":false,\"link\":null}},{\"name\":\"Dept\",\"path\":\"dept\",\"hidden\":false,\"component\":\"system/dept/index\",\"meta\":{\"title\":\"部门管理\",\"icon\":\"tree\",\"noCache\":false,\"link\":null}},{\"name\":\"Post\",\"path\":\"post\",\"hidden\":false,\"component\":\"system/post/index\",\"meta\":{\"title\":\"岗位管理\",\"icon\":\"post\",\"noCache\":false,\"link\":null}},{\"name\":\"Dict\",\"path\":\"dict\",\"hidden\":false,\"component\":\"system/dict/index\",\"meta\":{\"title\":\"字典管理\",\"icon\":\"dict\",\"noCache\":false,\"link\":null}},{\"name\":\"Config\",\"path\":\"config\",\"hidden\":false,\"component\":\"system/config/index\",\"meta\":{\"title\":\"参数设置\",\"icon\":\"edit\",\"noCache\":false,\"link\":null}},{\"name\":\"Notice\",\"path\":\"notice\",\"hidden\":false,\"component\":\"system/notice/index\",\"meta\":{\"title\":\"通知公告\",\"icon\":\"message\",\"noCache\":false,\"link\":null}},{\"name\":\"Log\",\"path\":\"log\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"ParentView\",\"alwaysShow\":true,\"meta\":{\"title\":\"日志管理\",\"icon\":\"log\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"Operlog\",\"path\":\"operlog\",\"hidden\":false,\"component\":\"monitor/operlog/index\",\"meta\":{\"title\":\"操作日志\",\"icon\":\"form\",\"noCache\":false,\"link\":null}},{\"name\":\"Logininfor\",\"path\":\"logininfor\",\"hidden\":false,\"component\":\"monitor/logininfor/index\",\"meta\":{\"title\":\"登录日志\",\"icon\":\"logininfor\",\"noCache\":false,\"link\":null}}]}]},{\"name\":\"Monitor\",\"path\":\"/monitor\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"Layout\",\"alwaysShow\":true,\"meta\":{\"title\":\"系统监控\",\"icon\":\"monitor\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"Online\",\"path\":\"online\",\"hidden\":false,\"component\":\"monitor/online/index\",\"meta\":{\"title\":\"在线用户\",\"icon\":\"online\",\"noCache\":false,\"link\":null}},{\"name\":\"Job\",\"path\":\"job\",\"hidden\":false,\"component\":\"monitor/job/index\",\"meta\":{\"title\":\"定时任务\",\"icon\":\"job\",\"noCache\":false,\"link\":null}},{\"name\":\"Druid\",\"path\":\"druid\",\"hidden\":false,\"component\":\"monitor/druid/index\",\"meta\":{\"title\":\"数据监控\",\"icon\":\"druid\",\"noCache\":false,\"link\":null}},{\"name\":\"Server\",\"path\":\"server\",\"hidden\":false,\"component\":\"monitor/server/index\",\"meta\":{\"title\":\"服务监控\",\"icon\":\"server\",\"noCache\":false,\"link\":null}},{\"name\":\"Cache\",\"path\":\"cache\",\"hidden\":false,\"component\":\"monitor/cache/index\",\"meta\":{\"title\":\"缓存监控\",\"icon\":\"redis\",\"noCache\":false,\"link\":null}},{\"name\":\"CacheList\",\"path\":\"cacheList\",\"hidden\":false,\"component\":\"monitor/cache/list\",\"meta\":{\"title\":\"缓存列表\",\"icon\":\"redis-list\",\"noCache\":false,\"link\":null}}]},{\"name\":\"Tool\",\"path\":\"/tool\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"Layout\",\"alwaysShow\":true,\"meta\":{\"title\":\"系统工具\",\"icon\":\"tool\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"Build\",\"path\":\"build\",\"hidden\":false,\"component\":\"tool/build/index\",\"meta\":{\"title\":\"表单构建\",\"icon\":\"build\",\"noCache\":false,\"link\":null}},{\"name\":\"Gen\",\"path\":\"gen\",\"hidden\":false,\"component\":\"tool/gen/index\",\"meta\":{\"title\":\"代码生成\",\"icon\":\"code\",\"noCache\":false,\"link\":null}},{\"name\":\"Swagger\",\"path\":\"swagger\",\"hidden\":false,\"component\":\"tool/swagger/index\",\"meta\":{\"title\":\"系统接口\",\"icon\":\"swagger\",\"noCache\":false,\"link\":null}}]},{\"name\":\"Http://ruoyi.vip\",\"path\":\"http://ruoyi.vip\",\"hidden\":false,\"component\":\"Layout\",\"meta\":{\"title\":\"若依官网\",\"icon\":\"guide\",\"noCache\":false,\"link\":\"http://ruoyi.vip\"}}]}";
//        JSONObject jsonObject = JSONUtil.parseObj(s);
//        Object data = jsonObject.get("data");
//        JSONArray array = JSONUtil.parseArray(data);
//
//        List<RouterVo> userList = JSONUtil.toList(array, RouterVo.class);
//
//        return R.ok().put("data",userList);
        Long userId = LoginUserUtil.getLoginUser().getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }
//    @PostMapping("/register")
//    public R register(@RequestBody RegisterBody user)
//    {
//        if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser"))))
//        {
//            return error("当前系统没有开启注册功能！");
//        }
//        String msg = registerService.register(user);
//        return StringUtils.isEmpty(msg) ? success() : error(msg);
//    }

    public static void main(String[] args) {
        String pwd = "861203";
        String password = new Sha256Hash(pwd, AuthConstants.SLAT_PWD).toHex();
        System.out.println(password);
    }
}


